//
//  global.h
//  Prism
//
//  Created by Bas du Pre on 19-05-11.
//  Copyright 2011 UU. All rights reserved.
//

extern int main(int argc, char** argv);

#define PRISM_VERSION_MAJOR     0
#define PRISM_VERSION_MINOR     0
#define PRISM_VERSION_REVISION  1

#define PRISM_DEBUGLAYER_UPDATE 0.2

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

#pragma once

extern void prism_initialize();
extern void prism_terminate();

#include <signal.h>
#include "LanguageExtensions.h"

#define __PRISM_MACRO_STRING_VALUE(s) __PRISM_MACRO_STRING(s)
#define __PRISM_MACRO_STRING(s) #s
#define PRISM_VERSIONSTRING Prism::String(Prism::String(__PRISM_MACRO_STRING_VALUE(PRISM_VERSION_MAJOR)) + \
                       Prism::String(".") + Prism::String(__PRISM_MACRO_STRING_VALUE(PRISM_VERSION_MINOR)) + \
                       Prism::String(".") + Prism::String(__PRISM_MACRO_STRING_VALUE(PRISM_VERSION_REVISION)))

#define PRISM_COMPILED_ON (Prism::String(__DATE__) + Prism::String(" ") + Prism::String(__TIME__))

#define PRISM_OS_IOS        0
#define PRISM_OS_ANDROID    0
#define PRISM_OS_CE         0
#define PRISM_OS_WIN        0
#define PRISM_OS_MAC        0
#define PRISM_OS_LINUX_X11  0
#define PRISM_OS_UNKNOWN    0
#define PRISM_CPU_X86       0
#define PRISM_CPU_ARM       0

#define PRISM_BITS_32       0
#define PRISM_BITS_64       0

#define PRISM_TARGET_SDL    0

#ifdef _WIN32
	#include "windows.h"
	#undef  PRISM_CPU_X86
    #define PRISM_CPU_X86     1
	#undef  PRISM_OS_WIN
    #define PRISM_OS_WIN      1

	#ifdef _WIN64
	#undef  PRISM_BITS_64
    #define PRISM_BITS_64     1
	#else
	#undef  PRISM_BITS_32
	#define PRISM_BITS_32     1
	#endif

	#undef  PRISM_TARGET_SDL 
    #define PRISM_TARGET_SDL  1
#endif

#ifdef __linux__
    #undef  PRISM_CPU_X86
    #define PRISM_CPU_X86     1
	#undef  PRISM_OS_LINUX_X11
    #define PRISM_OS_LINUX_X11 1

	#ifdef _LP64
	#undef  PRISM_BITS_64
    #define PRISM_BITS_64     1
	#else
	#undef  PRISM_BITS_32
	#define PRISM_BITS_32     1
	#endif

	#undef  PRISM_TARGET_SDL 
    #define PRISM_TARGET_SDL  1
#endif

#ifdef __APPLE__
    #include "TargetConditionals.h"

    #if TARGET_OS_IPHONE
    #undef  PRISM_OS_IOS
    #define PRISM_OS_IOS      1
    #endif

    #if TARGET_OS_MAC
    #undef  PRISM_OS_MAC
    #define PRISM_OS_MAC      1
    #undef  PRISM_TARGET_SDL 
    #define PRISM_TARGET_SDL  1
    #endif

    #if TARGET_CPU_X86_64
    #undef  PRISM_CPU_X86
    #undef  PRISM_BITS_64
    #define PRISM_CPU_X86     1
    #define PRISM_BITS_64     1
    #endif

    #if TARGET_CPU_X86
    #undef  PRISM_CPU_X86
    #undef  PRISM_BITS_32
    #define PRISM_CPU_X86     1
    #define PRISM_BITS_32     1
    #endif

    #if TARGET_CPU_ARM
    #undef  PRISM_CPU_ARM
    #undef  PRISM_BITS_32
    #define PRISM_CPU_ARM     1
    #define PRISM_BITS_32     1
    #endif

#endif

#if !PRISM_OS_IOS && !PRISM_OS_ANDROID && !PRISM_OS_CE && !PRISM_OS_CE && !PRISM_OS_WIN && !PRISM_OS_MAC && !PRISM_OS_LINUX_X11
    #undef  PRISM_OS_UNKNOWN
    #define PRISM_OS_UNKNOWN  1
#endif

#if PRISM_OS_ANDROID
#error "Android is not yet supported by Prism"
#endif
#if PRISM_OS_CE
#error "CE is not yet supported by Prism"
#endif
#if PRISM_OS_WIN
//#error "Windows is not yet supported by Prism"
// yes it is
#endif
#if PRISM_OS_MAC
//#error "Mac is not yet supported by Prism"
// yes it is
#endif
#if PRISM_OS_LINUX_X11
//#error "Linux/X11 is not yet supported by Prism"
// yes it is
#endif
#if PRISM_OS_UNKNOWN
#error "This is an unknown and therefor unsupported platform"
#endif

#if __cplusplus
#define PRISM_CPP 1
#else
#define PRISM_CPP 0
#endif

#if __OBJC__
#define PRISM_OBJC 1
#else
#define PRISM_OBJC 0
#endif

#if !defined(PRISM_DEBUG)
#if defined(NDEBUG)
#define PRISM_DEBUG 0
#else
#define PRISM_DEBUG 1
#endif
#endif

#if !defined(PRISM_BUILDENGINE)
#define PRISM_BUILDENGINE 1
#endif

#if PRISM_DEBUG == 0
#define PRISM_LOG(...) ;
#define PRISM_LOGERROR(...) ;
#define PRISM_LOGINFO(...) ;
#define PRISM_LOG_QUIET(...) ;
#define PRISM_LOGERROR_QUIET(...) ;
#define PRISM_LOGINFO_QUIET(...) ;

#elif PRISM_DEBUG == 1
#define PRISM_LOG(format, ...) Prism::Logger::instance()->logInternal(format, __FUNCTION__, __FILE__, __LINE__, ##__VA_ARGS__)
#define PRISM_LOGERROR(format, ...) Prism::Logger::instance()->logErrorInternal(format, __FUNCTION__, __FILE__, __LINE__, ##__VA_ARGS__)
#define PRISM_LOGINFO(format, ...) ;
#define PRISM_LOG_QUIET(format, ...) Prism::Logger::instance()->log(format, ##__VA_ARGS__)
#define PRISM_LOGERROR_QUIET(format, ...) Prism::Logger::instance()->logError(format, ##__VA_ARGS__)
#define PRISM_LOGINFO_QUIET(format, ...) ;

#elif PRISM_DEBUG > 1
#define PRISM_LOG(format, ...) Prism::Logger::instance()->logInternal(format, __FUNCTION__, __FILE__, __LINE__, ##__VA_ARGS__)
#define PRISM_LOGERROR(format, ...) Prism::Logger::instance()->logErrorInternal(format, __FUNCTION__, __FILE__, __LINE__, ##__VA_ARGS__)
#define PRISM_LOGINFO(format, ...) Prism::Logger::instance()->logInfoInternal(format, __FUNCTION__, __FILE__, __LINE__, ##__VA_ARGS__)
#define PRISM_LOG_QUIET(format, ...) Prism::Logger::instance()->log(format, ##__VA_ARGS__)
#define PRISM_LOGERROR_QUIET(format, ...) Prism::Logger::instance()->logError(format, ##__VA_ARGS__)
#define PRISM_LOGINFO_QUIET(format, ...) Prism::Logger::instance()->logInfo(format, ##__VA_ARGS__)
#endif // PRISM_DEBUG

// Breaks and Asserts
#if PRISM_DEBUG == 0
#define PRISM_DEBUG_BREAK() ;
#define PRISM_ASSERT_TRUE(...) ;
#define PRISM_ASSERT(...) ;
#define PRISM_ASSERT_FIX(...) ;
#define PRISM_ERROR(...) ;
#else
#ifdef _MSC_VER
#define PRISM_DEBUG_BREAK() if (IsDebuggerPresent()) { __debugbreak(); }
#else
#define PRISM_DEBUG_BREAK() if (posix_isDebuggerPresent()) { raise(SIGTRAP); }
#endif
#define PRISM_ASSERT_TRUE(expr) if (!(expr)) { PRISM_LOGERROR(Prism::String("Assert failed: ") + Prism::String(#expr)); PRISM_DEBUG_BREAK(); }
#define PRISM_ASSERT(expr, msg, ...) if (!(expr)) { PRISM_LOGERROR(Prism::String("Assert failed: ") + Prism::String(msg), ##__VA_ARGS__); PRISM_DEBUG_BREAK(); }
#define PRISM_ASSERT_FIX(expr, fix, msg, ...) if (!(expr)) { PRISM_LOGERROR(Prism::String("Assert failed: ") + Prism::String(msg), ##__VA_ARGS__); PRISM_DEBUG_BREAK(); fix; }
#define PRISM_ERROR(msg, ...) { PRISM_LOGERROR(Prism::String(msg), ##__VA_ARGS__); PRISM_DEBUG_BREAK(); }
#endif // PRISM_DEBUG


#include "primitives.h"

#include "PObject.h"

#include "Logger.h"

#include "functions.h"

#if PRISM_OS_IOS && PRISM_OBJC && PRISM_BUILDENGINE
#include "iOS/ios_global.h"
#elif PRISM_TARGET_SDL
#include "sdl/sdl_global.h" 
#endif
